﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Tanks
{
    public class Game
    {
        public  bool[] KeyList = new bool[256];
        public List<Explosion> Expl = new List<Explosion>();
        public List<Missile> Miss=new List<Missile>();
        public List<Item> Items=new List<Item>();
        public int Resolution = 96;
        public int CellSize
        {
            get
            {
                return 50*96/Resolution;
            }
        }
        List<Tank> tanks= new List<Tank>();
        public void RemoveTank(Tank t){
            tanks.Remove(t);
        }
        public int TanksCount
        {
            get
            {
                return tanks.Count;
            }
        }
        public IEnumerable<Tank> AllTanks
        {
            get
            {
                for (int i = 0; i < tanks.Count; i++)
                    yield return tanks[i];
            }
        }
        public Random rand = new Random();
        //________Singleton______________
            private static Game instance;
            protected Game()
            { 

            }
            public static Game Instance()
            {
                if (instance == null)
                    instance = new Game();

                return instance;
            }
        //_______________________________
            static int fieldWidth = 14;
            public int FieldWidth
            {
                get
                {
                    return fieldWidth;
                }
            }
            static int fieldHeight = 12;
            public int FieldHeight
            {
                get
                {
                    return fieldHeight;
                }
            }
            public Cell[,] Grid = new Cell[fieldWidth, fieldHeight];
            public void randomFillMap()
            {
                List<Cell> Destr= new List<Cell>();
                for (int i = 0; i < fieldWidth; i++)
                {
                    for (int j = 0; j < fieldHeight; j++)
                    {
                        if (i % 2 == 0 && j % 2 == 0)
                        {
                            Grid[i, j] = new Cell(BlockType.Solid,i,j);
                        }
                        else
                        {
                            if (30 > rand.Next(100))
                            {
                                Grid[i, j] = new Cell(BlockType.Destructible, i, j);
                                Destr.Add(Grid[i,j]);
                            }
                            else
                            {
                                Grid[i, j] = new Cell(BlockType.Empty, i, j);                                
                            }
                        }
                    }                    
                }
                int rnd = rand.Next(Destr.Count - 1);
                Items.Add(new Item_Launcher(Destr[rnd]));
                Destr.Remove(Destr[rnd]);
                rnd = rand.Next(Destr.Count - 1);
                Items.Add(new Item_Plasmagun(Destr[rnd]));
                Destr.Remove(Destr[rnd]);
                for (int i = 1; i <= 3; i++)
                {
                    rnd = rand.Next(Destr.Count - 1);
                    Items.Add(new Healthpack(Destr[rnd]));
                    Destr.Remove(Destr[rnd]);
                }
                AddTank(new KeyboardController(new KeyboardLayout(37,39,38,40,16,17)));
                AddTank(new KeyboardController(new KeyboardLayout(65, 68, 87, 83, 69,81)));

                AddTank(new AIcontroller());

            }
            public void AddTank(Controller c)
            {
                int _x = rand.Next((int)Math.Floor((Decimal)((fieldWidth - 2) / 2))) * 2 + 1;
                int _y = rand.Next((int)Math.Floor((Decimal)((fieldHeight - 2) / 2))) * 2 + 1;
                try
                {
                    AddTank(_x, _y,c);
                }
                catch(Exception ex)
                {
                    if(ex.Message=="Invalid Tank Placement"){
                        AddTank(c);
                    }
                }
            }
            
            public void AddTank(int X, int Y, Controller c)
            {
                if (Grid[X, Y].currTank == null)
                {
                    tanks.Add(new Tank(X, Y,c));
                }
                else
                {
                   throw(new Exception("Invalid Tank Placement"));
                }
            }
            public void Explode(int Range, Cell c,int s)
            {
                if (c.Block == BlockType.Destructible)
                {
                    c.Block = BlockType.Empty;
                }
                Expl.Add(new Explosion(c,s));
                for (int i = 1; i < Range; i++)
                {
                    if (c.X + i < fieldWidth && Grid[c.X + i, c.Y].Block!=BlockType.Solid)
                    {
                        Explode(1, Grid[c.X + i, c.Y], (int)Math.Round((double)(s / i)));
                    }
                    else
                    {
                        break;
                    }
                }
                for (int i = 1; i < Range; i++)
                {
                    if (c.X - i >= 0 && Grid[c.X - i, c.Y].Block != BlockType.Solid)
                    {
                        Explode(1, Grid[c.X - i, c.Y], (int)Math.Round((double)(s / i)));
                    }
                    else
                    {
                        break;
                    }
                }
                for (int i = 1; i < Range; i++)
                {
                    if (c.Y + i < fieldHeight && Grid[c.X, c.Y + i].Block != BlockType.Solid)
                    {
                        Explode(1, Grid[c.X, c.Y + i], (int)Math.Round((double)(s / i)));
                    }
                    else{
                        break;
                    }
                }
                for (int i = 1; i < Range; i++)
                {
                    if (c.Y - i >= 0 && Grid[c.X, c.Y - i].Block != BlockType.Solid)
                    {
                        Explode(1, Grid[c.X, c.Y - i], (int)Math.Round((double)(s / i)));
                    }else{
                        break;
                    }
                }
            }   
        
    }
}
